import json
import logging
import os
from datetime import datetime
from typing import Optional

from api.service.simliar_index_service import matcher
from models import db
from models.rule import MatAttrData, MaterialMaster, MatCategoryAttrMaster, MatAttrPoolMaster, MatCategoryAttr, Material

# 配置
LAST_SYNC_FILE = "last_sync_time.json"
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"

logger = logging.getLogger(__name__)


def get_last_sync_time() -> Optional[datetime]:
    """读取上次同步的时间"""
    if not os.path.exists(LAST_SYNC_FILE):
        return None

    try:
        with open(LAST_SYNC_FILE, "r", encoding="utf-8") as f:
            data = json.load(f)
            last_time_str = data.get("last_sync_time")
            if last_time_str:
                return datetime.strptime(last_time_str, DATETIME_FORMAT)
    except (json.JSONDecodeError, KeyError, ValueError) as e:
        print(f"读取上次同步时间失败: {e}")
        return None
    return None


def save_last_sync_time(sync_time: datetime):
    """保存本次同步的时间"""
    with open(LAST_SYNC_FILE, "w", encoding="utf-8") as f:
        json.dump(
            {"last_sync_time": sync_time.strftime(DATETIME_FORMAT)},
            f,
            ensure_ascii=False,
            indent=2
        )


def fetch_data_from_source(since_time: Optional[datetime] = None, category_tree_code=None):
    """
    从数据源获取数据
    - 如果 since_time 为 None：全量拉取
    - 否则：增量拉取 updated_at >= since_time 的数据
    """
    # 构建查询
    try:
        cate_code_map = get_category_valid_attr_codes(since_time, category_tree_code)
        query = get_category_valid_attr_data(since_time, category_tree_code)
        for attr_data, category_tree_code in query.yield_per(1000):
            try:
                required_attrs = cate_code_map.get(category_tree_code)
                process_data(attr_data, required_attrs, category_tree_code)
            except Exception as e:
                logger.error(e)
    finally:
        db.session.close()


def process_data(attr_json_data, required_attrs, category_tree_code):
    print(f"Processing category_tree_code: {category_tree_code}, attr_data: {attr_json_data}")
    import json
    try:
        data_dict = json.loads(attr_json_data)
        print("Parsed attributes:", data_dict)
    except (json.JSONDecodeError, TypeError) as e:
        logger.warning(f"Failed to parse attr_data: {e}")
        data_dict = {}

    for item in data_dict:
        if item["code"] in required_attrs:
            matcher.add_candidate(item, category=category_tree_code)
            pass


def get_category_valid_attr_data(since_time: Optional[datetime], category_tree_code=None, ):
    # 使用 JOIN 一次性获取有效属性
    query = db.session.query(
        MatAttrData.attr_data,
        MaterialMaster.category_tree_code
    ).join(
        Material,
        Material.id == MatAttrData.material_id
    ).join(
        MaterialMaster,
        MaterialMaster.id == Material.master_id  # 确认这层关系
    ).filter(
        MatAttrData.delete_flag == 0,
        MaterialMaster.delete_flag == 0,
        Material.delete_flag == 0
    )
    # 动态添加条件
    if category_tree_code:
        query = query.filter(MaterialMaster.category_tree_code == category_tree_code)
    if since_time:
        query = query.filter(MatAttrData.last_update_date >= since_time)

    return query


def get_category_valid_attr_codes(since_time: Optional[datetime], category_tree_code=None):
    from collections import defaultdict

    # 使用 JOIN 一次性获取有效属性
    query = db.session.query(
        MatCategoryAttrMaster.category_tree_code,
        MatAttrPoolMaster.code
    ).join(
        MatAttrPoolMaster,
        MatAttrPoolMaster.id == MatCategoryAttrMaster.attr_pool_master_id
    ).join(
        MatCategoryAttr,
        MatCategoryAttr.master_id == MatCategoryAttrMaster.id  # 确认这层关系
    ).filter(
        MatCategoryAttr.is_assign_code_valid == 'Y',
        MatCategoryAttr.delete_flag == 0,
        MatCategoryAttrMaster.delete_flag == 0,
        MatAttrPoolMaster.delete_flag == 0
    )

    # 动态添加条件
    if category_tree_code:
        query = query.filter(MatCategoryAttrMaster.category_tree_code == category_tree_code)
    if since_time:
        query = query.filter(MatCategoryAttrMaster.last_update_date >= since_time)

    result = defaultdict(list)
    for cat_code, attr_code in query.all():
        if cat_code:  # 排除空分类
            result[cat_code].append(attr_code)

    return dict(result)


def sync_data():
    # 1. 获取上次同步时间
    last_sync_time = get_last_sync_time()

    # 2. 获取当前时间作为本次同步的“截止时间”
    current_sync_time = datetime.now()

    # 3. 从数据源拉取数据
    fetch_data_from_source(last_sync_time, None)

    # 4. 更新同步时间（即使没有数据也要更新时间戳，避免重复拉取）
    save_last_sync_time(current_sync_time)
    print(f"同步完成，下次将从 {current_sync_time.strftime(DATETIME_FORMAT)} 开始同步。")


if __name__ == "__main__":
    sync_data()
